package spring.mvc.config.converter;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.AbstractHttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.Properties;

/**
 * https://blog.csdn.net/f641385712/article/details/89891245
 * https://blog.csdn.net/f641385712/article/details/90316116
 * 自定义消息转换器 PropertiesHttpMessageConverter 处理 Properties 类型数据
 * 此处我们只处理我们自定义的：application/properties-user 这一种 MediaType，职责范围放到最小。
 * 访问时请求头 Content-Type 设置成 application/properties-user
 * 根据 Content-Type 头部，将 body 字符串转换为 java 对象。反过来，根据 Accept 头部，将 java 对象转换为客户端期望格式的字符串。
 * Request 请求头中的 Accept 属性的值，也被称为 MediaType
 * 一个 HTTP 请求没有指定 Accept，默认视为指定 Accept: /。请求头里没有指定 Content-Type，默认视为 null，就是没有。
 * Content-Type 若指定了，必须是具体确定的类型，不能包含 *.
 * 消息转换器都放在了 RequestMappingHandlerAdapter，开启了 @EnableWebMvc 会多注册几个
 */
public class PropertiesHttpMessageConverter extends AbstractHttpMessageConverter<PropertiesHttpMessageConverter.User> {
    // 用于仅仅只处理我自己自定义的指定的 MediaType
    private static final MediaType DEFAULT_MEDIATYPE = MediaType.valueOf("application/properties-user");

    public PropertiesHttpMessageConverter() {
        super(DEFAULT_MEDIATYPE);
        setDefaultCharset(StandardCharsets.UTF_8);
    }

    // 要求入参、返回值必须是User类型我才处理
    @Override
    protected boolean supports(Class<?> clazz) {
        return clazz.isAssignableFrom(User.class);
    }

    @Override
    protected User readInternal(Class<? extends User> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
        InputStream is = inputMessage.getBody();
        Properties props = new Properties();
        props.load(is);

        // user 的三个属性
        String id = props.getProperty("id");
        String name = props.getProperty("name");
        String age = props.getProperty("age");
        return new User(Long.valueOf(id), name, Integer.valueOf(age));
    }

    @Override
    protected void writeInternal(User user, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
        OutputStream os = outputMessage.getBody();
        Properties properties = new Properties();

        // 属性判空此处我就不做了
        properties.setProperty("id", user.getId().toString());
        properties.setProperty("name", user.getName());
        properties.setProperty("age", user.getAge().toString());
        properties.store(os, "user comments");
    }

    @Getter
    @Setter
    @AllArgsConstructor
    static class User {
        Long id;
        String name;
        Integer age;
    }
}
